<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>爱心</title>
    <style>
        .container{
            background-color: black;
        }
    </style>
</head>
<body>
  <!--全局容器-->
   <div  class="container">

   </div>
</body>
<script src="js/jquery.js"></script>
<script>

    $(function () {

        /* 方法三 极度推荐

      这是用第一种方法得到的坐标，可以直挨用，减少CPU使用*/
        var  angle_coord_list=[
            [0.00,-200.00],[-86.60,-150.00],[-117.49,-130.08],[-146.28,-107.24],[-172.69,-81.68],

            [-196.46,-53.65],[-217.38,-23.43],[-235.23,8.69],[-249.85,42.41],[-261.09,77.40],

            [-265.49,102.74],[-265.28, 128.46],[-260.47,153.73],[-251.21,177.73],[-237.81,199.68],[-220.69,218.88],[-200.41,234.70],[-177.63,246.64],[-153.08,254.31],[-127.55,257.46],[-101.87,255.99],[-76.87,249.94],[-53.36,239.52],[-32.09,225.05],[-13.75,207.02],

            [1.06,185.99],[15.87,207.02],[34.21,225.05],[55.48,239.52],[78.99,249.94],

            [103.99,255.99],[129.67,257.46],[155.20,254.31],[179.75,246.64], [202.53,234.70],[222.81,218.88],[239.93,199.68],[253.33,177.73],[262.59,153.73],[267.40,128.46],[267.61,102.74],[263.21,77.40],[251.97,42.41],[237.35,8.69],[219.50,-23.43],

            [198.58,-53.65],[174.81,-81.68],[148.40,-107.24],[119.61,-130.08],[88.72,-150.00],

            [2.12,-200.00]
        ];

        /* 第三步：处理上述坐标{第一种方法），获得更多详细坐标*/

        //初始化新爱心坐标列表
        var  new_coord_list=[];

        //用旧坐标生成新坐标
        angle_coord_list.forEach((order2, angle_coord) =>{
            if (order2 +1 < angle_coord_list.length){
                //以O，25为间隔，计算两点之间需要分成多少份
                var pointnum_x=Math.abs(angle_coord_list[order2+1][0]-angle_coord_list[order2][0])/0.25;
                var pointnum_y=Math.abs(angle_coord_list[order2+1][1]-angle_coord_list[order2][1])/0.25;//取两值之间大的一个，如果不取，会出现点分布不均匀的情况
                var pointnum = Math.max(pointnum_x, pointnum_y);
                //计算两点之间 横织左边的最小步距
                var step_x=((angle_coord_list[order2+1][0]-angle_coord_list[order2][0])/pointnum);
                var step_y=((angle_coord_list[order2+1][1]-angle_coord_list[order2][1])/pointnum)//一次得出新坐标的每个X，Y值
                pointnum.forEach(i =>{
                    var new_coord=[(angle_coord_list[order2][0] +(i +1)* step_x).toFixed(2),
                        (angle_coord_list[order2][1] +(i +1) * step_y).toFixed(2)];
                    if(new_coord_list.includes(new_coord)){
                        new_coord_list.push(new_coord);
                    }

                })
            }
        });

        var self = {
            //运行主过程
            //self.startTimer(50);//设置界面刷新时间1000=1s（电脑算力不够会不流畅)
            readlist: 0,// 画面显示的第几界面（用10个界面的不规律循环产生心跳效果）
            largen : true,// 确定心脏是该收缩还是舒展
            cen_x :$(window).width/2,//确定心脏的中心点橱坐标
            cen_y:$(window).height/2-50,//确定心脏的中心点纵坐标
            cent : 100, //弥补心脏中心空洞的矩形范围的一半
            width:$(window).width,
            height:$(window).height,
            coord_list1:[],
            all_coord_list1:[]
        };

        makecoord(self);

        self.all_coord_list1.forEach(item =>{
            item.forEach(items =>{
                canvas.width  = canvas.clientWidth;
                canvas.height = canvas.clientHeight;
            })
        })
    });



   /*第五步：产生中间爱心点的坐标、大小、颜色*/
   //产生主爱心的点
//生成所有点的坐标及属性
function makecoord(self){
    self.coord_list1 = [];
        //初始化主心脏的坐标列表
    self.all_coord_list1=[]; // 初始化主心脏跳动起来（每帧）的所有坐标列表
    //确定爱心从外层到内层，各个层级的稠密程度
    //用圆形'×平方+y平方=100的平方'的公式确定延伸,
    //因为当x趋近于0时，y不仅值大且y变化平缓，正好符合剧中爱心的外密内稀
    //我尝试过高斯分布等，效果都没这个好
    var expend_list=[];
    for(var i=0;i<105;i+5){
        expend_list.push(9*(Math.sqrt(10000-(i*i).toFixed(4))+200));
    }
    //用循环读取稠密程度列表
    expend_list.forEach((order, expend) =>{
        //偏移程度参数，越内圈越离散，
        //（这个公式别间为什么，巨复杂)
        var offset=((expend_list.length)-Math.sqrt(((expend_list.length)**2 -((order+1)**2))+order+2)*0.8)
        //读取爱心坐标来生成更多点
        new_coord_list.forEach(new_coord =>{
            //这一步可以控制生成点的多少，现在我设置的只输出1/8的点，
            if(getRandom(1,8)===1){
                var size = getRandom(1,4);
                //调用上边的稠密程度参数生成内外各个层级的点
                var heart_x=(new_coord[0] *(Math.sqrt(expend) * 0.024));
                var heart_y=(new_coord[1] *(Math.sqrt(expend) * 0.026))
                // 转换为屏幕中心的点，因为屏幕左上角才为ougt5的(G，0)点
                var x = heart_x + self.width/2;
                var y = heart_y + self.height/2;
                //随机生成偏移
                var draw_x = x + getRandom(-offset,offset);
                var draw_y = y + getRandom(-offset,offset);
                //随机生成颜色（我用PS试的颜色，可以自己调整)
                var colorint = getRandom(1,7);
                var color;
                if(colorint===1){
                    color = "#aa4431"
                }
                if(colorint===2){
                    color = "#ff41cc"
                }
                if(colorint===3){
                    color = "#f2b4ff"
                }
                if(colorint===4){
                    color = "#ff53b1"
                }
                if(colorint===5){
                    color = "#aaaaaa"
                }
                //为了省内存，也为了画面更流畅，这里只添加不同坐标、属性的点
                //if (draw_x, draw_y, size, color) not in self.coord_list1:
                self.coord_list1.push({draw_x, draw_y, size,color})

            }
        })
    })
    //把初始化的爱心点列表作为画面第1帧
    self.all_coord_list1.push(self.coord_list1);

}









  /* #！！！重点来了！！！下面做出心脏跳动的效果
   for su in range(1,10):# 因为我分了10帧，所以要生成后9帧的点
   coord_temporary1 =[]
   #遍历第1帧所有点
   for coord in self.coord_list1:
   #跳动效果公式
   #基本原理是根据各点与中心点的距离远近改变向外放大的程度
   #就有了内圈变化更剧烈的效果（跳动）
flexk=((536-1.11111111111*sqrt(((coord[0]-self.cen_x)**2)+
    ((coord[1]-self.cen_y)**2)))*(0.00006)*su)-(su*0.01+0.017)
”保证放大参数为正数
   if flexk < 0:
   flexk=0
   #高中学的以特定点为中心放大缩小公式
   new_x = self.cen_x - (1 + flexk) * (self.cen_x - coord[0])new_y = self.cen_y - (1 + flexk) * (self.cen_y - coord[1])#收集起来
   coord_temporary1.append((new_x, new_y, coord[2], coord[3]))
   #保存到下一帧
   self.all_coord_list1.append(coord_temporary1)
   #产生爱心外面飘败的点----
       #这部分同产生主爱心的原理，参数有调整，不再赘述
   self.coord_list2=[]
   self.all_coord_list2 =[]# 这个列表的点为实时无规律变化，不同于主爱心的点有规律
   #注意这1只到90，否则爱心中心不好看
   expend_list=[int(round(sqrt(10000-(i*i))+100-i,4)) for i in range(0,92,5)]
   fon onden exnand in enumenatelexnend ist);
×*/



function getRandom(min, max) {
    return Math.floor(Math.random() * (max - min + 1)) + min;
}


</script>
</html>